package com.gy.spark.core;

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.Optional;
import org.apache.spark.api.java.function.*;
import scala.Tuple2;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class Day02JAVA {
    public static void main(String[] args) {
        SparkConf conf = new SparkConf().setAppName(Day02JAVA.class.getSimpleName()).setMaster("local");
        JavaSparkContext sc = new JavaSparkContext(conf);

        JavaRDD<String> rdd = sc.parallelize(Arrays.asList("a", "a", "a", "a", "a", "a", "a"));


        JavaRDD<String> distinctRdd = rdd.distinct();
        distinctRdd.foreach(new VoidFunction<String>() {
            @Override
            public void call(String s) throws Exception {
                System.err.println(s);
            }
        });


        JavaPairRDD<String, Integer> pairRDD = rdd.mapToPair(new PairFunction<String, String, Integer>() {
            @Override
            public Tuple2<String, Integer> call(String s) throws Exception {
                return new Tuple2<String, Integer>(s, 1);
            }
        });

        JavaPairRDD<String, Integer> reduceByKeyRDD = pairRDD.reduceByKey(new Function2<Integer, Integer, Integer>() {
            @Override
            public Integer call(Integer v1, Integer v2) throws Exception {
                return v1 + v2;
            }
        });

        JavaRDD<String> mapRDD = reduceByKeyRDD.map(new Function<Tuple2<String, Integer>, String>() {
            @Override
            public String call(Tuple2<String, Integer> v1) throws Exception {
                return v1._1;
            }
        });

        mapRDD.foreach(new VoidFunction<String>() {
            @Override
            public void call(String s) throws Exception {
                System.err.println(s);
            }
        });

        rdd.foreachPartition(new VoidFunction<Iterator<String>>() {
            @Override
            public void call(Iterator<String> iter) throws Exception {
                ArrayList<String> list = new ArrayList<>();
                System.out.println("打开连接。。。");
                while (iter.hasNext()) {
                    String str = iter.next();
                    System.err.println("。。。拼接sql");
                    list.add(str);
                }
                System.out.println("关闭连接。。。");
            }
        });

        JavaRDD<String> mapPartitionRDD = rdd.mapPartitions(new FlatMapFunction<Iterator<String>, String>() {
            @Override
            public Iterator<String> call(Iterator<String> iter) throws Exception {
                List<String> list = new ArrayList<String>();

                System.out.println("创建数据库连接。。。。");

                while (iter.hasNext()) {
                    String s = iter.next();
                    System.out.println("拼接sql。。。。" + s);
                    list.add(s);
                }

                System.out.println("关闭数据库连接。。。。");
                return list.iterator();
            }
        });

        mapPartitionRDD.collect();

        System.out.println("--------------  cogroup  ---------------");


        JavaPairRDD<String, String> rdd1 = sc.<String, String>parallelizePairs(Arrays.asList(
                new Tuple2<String, String>("zhangsan", "a"),
                new Tuple2<String, String>("zhangsan", "aa"),
                new Tuple2<String, String>("zhangsan", "aaa"),
                new Tuple2<String, String>("lisi", "b"),
                new Tuple2<String, String>("lisi", "bb"),
                new Tuple2<String, String>("wangwu", "c")
        ));


        JavaPairRDD<String, String> rdd2 = sc.<String, String>parallelizePairs(Arrays.asList(
                new Tuple2<String, String>("zhangsan", "10000"),
                new Tuple2<String, String>("lisi", "1"),
                new Tuple2<String, String>("lisi", "10"),
                new Tuple2<String, String>("lisi", "b"),
                new Tuple2<String, String>("lisi", "1000"),
                new Tuple2<String, String>("wangwu", "3"),
                new Tuple2<String, String>("wangwu", "30"),
                new Tuple2<String, String>("maliu", "200")
        ));

        /**
         * [key:[v1.values:v2.values]]
         */
        JavaPairRDD<String, Tuple2<Iterable<String>, Iterable<String>>> cogroupRDD = rdd1.<String>cogroup(rdd2);
        cogroupRDD.foreach(new VoidFunction<Tuple2<String, Tuple2<Iterable<String>, Iterable<String>>>>() {
            @Override
            public void call(Tuple2<String, Tuple2<Iterable<String>, Iterable<String>>> iter) throws Exception {
                String v1 = iter._1;
                System.out.print("key:" + v1);
                System.out.print("\t");
                Tuple2<Iterable<String>, Iterable<String>> v2 = iter._2;
                Iterable<String> v2_1 = v2._1;
                for (String str : v2_1) {
                    System.out.print("v_key:" + str);
                }
                Iterable<String> v2_2 = v2._2;
                System.out.print("\t");
                for (String str : v2_2) {
                    System.out.print("v_val:" + str);
                }
                System.out.println();
            }
        });

        /**
         * 取差集
         */
        JavaPairRDD<String, String> subtractRDD = rdd2.subtract(rdd1);
        subtractRDD.foreach(new VoidFunction<Tuple2<String, String>>() {
            @Override
            public void call(Tuple2<String, String> tuple2) throws Exception {
                System.out.println(tuple2._1 + "\t" + tuple2._2);
            }
        });


        /**
         * 取交集
         */
        JavaPairRDD<String, String> intersectionRDD = rdd1.intersection(rdd2);
        intersectionRDD.foreach(new VoidFunction<Tuple2<String, String>>() {
            @Override
            public void call(Tuple2<String, String> tuple2) throws Exception {
                System.out.println(tuple2._1 + "\t" + tuple2._2);
            }
        });


        JavaPairRDD<String, Integer> rdd3 = sc.<String, Integer>parallelizePairs(Arrays.asList(
                new Tuple2<String, Integer>("zhangsan", 100),
                new Tuple2<String, Integer>("lisi", 200),
                new Tuple2<String, Integer>("wangwu", 300),
                new Tuple2<String, Integer>("tianqi", 400)
        ), 2);
        JavaPairRDD<String, String> rdd4 = sc.<String, String>parallelizePairs(Arrays.asList(
                new Tuple2<String, String>("zhangsan1", "100"),
                new Tuple2<String, String>("zhangsan", "a"),
                new Tuple2<String, String>("lisi1", "200"),
                new Tuple2<String, String>("wangwu1", "300"),
                new Tuple2<String, String>("tianqi1", "400")
        ), 2);


        /**
         * union合并  有重复
         */
        System.out.println("========= union ===========");
        JavaPairRDD<String, String> unionRDD = rdd1.union(rdd4);
        unionRDD.foreach(new VoidFunction<Tuple2<String, String>>() {
            @Override
            public void call(Tuple2<String, String> tuple2) throws Exception {
                System.err.println(tuple2._1 + "\t" + tuple2._2);
            }
        });

        JavaPairRDD<String, Tuple2<String, Optional<Integer>>> leftRDD = rdd4.<Integer>leftOuterJoin(rdd3);
        leftRDD.foreach(new VoidFunction<Tuple2<String, Tuple2<String, Optional<Integer>>>>() {
            @Override
            public void call(Tuple2<String, Tuple2<String, Optional<Integer>>> tuple2) throws Exception {
                System.err.println(tuple2._1 + "\t" + tuple2._2);
            }
        });

        sc.stop();
    }
}
